﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using SeizyUtils.Common.Utilities;
using System.Text.RegularExpressions;

namespace SeizyUtils.Common.Data.Database.Parse
{
    class QueryParser
    {
        /// <summary>
        /// IQueryを解析し、パラメータを加えたSQLを生成します。
        /// </summary>
        /// <param name="query"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public static string ParseQuery(IQuery query, QueryParam param)
        {
            StringBuilder resultSql = new StringBuilder();
            IParseState state = new ReadState();

            string baseQuery = query.getQuery();
            StringReader reader = new StringReader(baseQuery);

            while(reader.Peek() > -1){
                
                string line = reader.ReadLine().TrimStart();
                state = state.ReadLine(line, resultSql, param);
            }

            string sql = resultSql.ToString();
            return sql;
        }

        /// <summary>
        /// パラメータを置換し、置換後の文字列を返します。
        /// パラメータは存在するが、paramのカラム名に存在しないパラメータだった場合は空文字列を返します。
        /// パラメータが存在しないときは、渡された文字列をそのまま返します。
        /// </summary>
        /// <param name="line"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public static string replaceParam(String line, QueryParam param)
        {
            // パラメータの解析
            Regex regex = new Regex("@.*@");
            Match match = regex.Match(line);
            if (match.Success)
            {

                // パラメータ名の取得
                string paramName = match.Value;
                string columnName = paramName.Substring(paramName.IndexOf('@') + 1, paramName.Length - 2);

                // パラメータが存在する場合
                if (param.contains(columnName))
                {
                    object value = param.get(columnName);
                    string valueString = TypeUtils.castString(value);
                    string result = null;
                    string stringParam = "'" + paramName + "'";
                    int index = line.IndexOf(stringParam);
                    if (valueString == null)
                    {
                        //パラメータがシングルクォートで囲まれているとき
                        if (index >= 0)
                        {
                            result = line.Replace(stringParam, "NULL");
                        }
                        else
                        {
                            result = line.Replace(paramName, "NULL");
                        }
                    }
                    else
                    {   
                        //パラメータがシングルクォートで囲まれているとき
                        if (index >= 0)
                        {
                            result = line.Replace(paramName, valueString.Replace("'", "''"));
                        }
                        else
                        {
                            result = line.Replace(paramName, valueString);
                        }
                    }

                    return result;
                }
                // パラメータが存在しない場合
                else
                {
                    return string.Empty;
                }
            }
            return line;
        }
    }
}
